﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Runtime.Serialization;
using System.IO;
using System.Xml.Serialization;
using RaveEngine.Engine.Query.Aggregate;

namespace RaveEngine.Engine.Query
{
    public class AggregateQuery : BaseRaveQuery
    {
        public AggregateQuery() { }

        public AggregateQuery(Stream sConfigStream)
        {
            try
            {
                XmlSerializer serializer = new XmlSerializer(typeof(raveAggregateConfig));
                config = (raveAggregateConfig)serializer.Deserialize(sConfigStream);
            }
            catch (Exception ex)
            {
                throw new Exception("Invalid Rave Configuration", ex);
            }
        }

        public override object Process()
        {
            HtmlScrape hDoc;
            List<AggregateResponse> list = new List<AggregateResponse>();
            AggregateResponse item;
            string sXsltOutput;
            raveAggregateConfig tconfig = config as raveAggregateConfig;

            // Scrape Urls
            for (int i = 0; tconfig.urls != null && i < tconfig.urls.Length; i++)
            {
                hDoc = new HtmlScrape(tconfig.urls[i]);
                item = new AggregateResponse();

                #region Process each operation data field from scrape.

                for (int j = 0; tconfig.dataFields != null && j < tconfig.dataFields.Length; j++)
                {
                    if (string.IsNullOrEmpty(tconfig.dataFields[j].type))
                    {
                        throw new Exception(string.Format("Rave configuration is not valid. The data field {0} has a null type", tconfig.dataFields[j].name));
                    }
                    switch (tconfig.dataFields[j].type.ToLowerInvariant())
                    {
                        case "literal":
                            item.data.Add(new AggregateItemData() { name = tconfig.dataFields[j].name, value = tconfig.dataFields[j].value });
                            break;
                        case "xslt":
                            try
                            {
                                sXsltOutput = hDoc.ProcessXslt(tconfig.dataFields[j].value);
                                item.data.Add(new AggregateItemData() { name = tconfig.dataFields[j].name, value = QueryHelpers.PostProcessRegex(sXsltOutput, tconfig.dataFields[j].postRegex) });
                            }
                            catch (Exception ex1)
                            {
                                item.data.Add(new AggregateItemData() { name = tconfig.dataFields[j].name, value = string.Format("ERROR - {0}", ex1.Message) });
                            }
                            break;
                        default:
                            break;
                    }
                }
                #endregion

                list.Add(item);
            }

            return list;
        }
    }
}